import os
import uuid
from werkzeug.utils import secure_filename
from flask import current_app
from datetime import datetime

class FileUploadHandler:
    """文件上传处理工具类"""
    
    # 允许的文件扩展名
    ALLOWED_EXTENSIONS = {
        'image': ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'],
        'document': ['pdf', 'doc', 'docx', 'txt', 'rtf', 'odt'],
        'archive': ['zip', 'rar', '7z', 'tar', 'gz'],
        'media': ['mp3', 'wav', 'mp4', 'avi', 'mov', 'flv']
    }
    
    # 最大文件大小 (字节)
    MAX_FILE_SIZE = 16 * 1024 * 1024  # 16MB
    
    @classmethod
    def allowed_file(cls, filename):
        """检查文件扩展名是否被允许"""
        if not filename:
            return False
        
        # 获取文件扩展名
        ext = filename.rsplit('.', 1)[1].lower() if '.' in filename else ''
        
        # 检查是否在允许的扩展名列表中
        for category, extensions in cls.ALLOWED_EXTENSIONS.items():
            if ext in extensions:
                return True
        
        return False
    
    @classmethod
    def get_file_category(cls, filename):
        """获取文件类别"""
        if not filename:
            return 'unknown'
        
        ext = filename.rsplit('.', 1)[1].lower() if '.' in filename else ''
        
        for category, extensions in cls.ALLOWED_EXTENSIONS.items():
            if ext in extensions:
                return category
        
        return 'unknown'
    
    @classmethod
    def generate_unique_filename(cls, filename):
        """生成唯一的文件名"""
        if not filename:
            return None
        
        # 获取安全的文件名
        secure_name = secure_filename(filename)
        
        # 如果文件名为空，使用UUID
        if not secure_name:
            secure_name = str(uuid.uuid4())
        
        # 获取文件扩展名
        ext = ''
        if '.' in secure_name:
            ext = '.' + secure_name.rsplit('.', 1)[1].lower()
            base_name = secure_name.rsplit('.', 1)[0]
        else:
            base_name = secure_name
        
        # 生成唯一文件名: 时间戳_UUID_原文件名
        timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
        unique_id = str(uuid.uuid4())[:8]
        
        return f"{timestamp}_{unique_id}_{base_name}{ext}"
    
    @classmethod
    def save_file(cls, file, upload_folder=None):
        """保存上传的文件"""
        if not file:
            return None, "没有选择文件"
        
        # 检查文件大小
        file.seek(0, os.SEEK_END)
        file_size = file.tell()
        file.seek(0)
        
        if file_size > cls.MAX_FILE_SIZE:
            return None, f"文件大小超过限制 ({cls.MAX_FILE_SIZE / (1024*1024):.1f}MB)"
        
        # 检查文件类型
        if not cls.allowed_file(file.filename):
            return None, "不支持的文件类型"
        
        # 使用默认上传文件夹
        if upload_folder is None:
            upload_folder = current_app.config.get('UPLOAD_FOLDER', 'app/static/uploads')
        
        # 确保上传目录存在
        os.makedirs(upload_folder, exist_ok=True)
        
        # 生成唯一文件名
        filename = cls.generate_unique_filename(file.filename)
        file_path = os.path.join(upload_folder, filename)
        
        try:
            # 保存文件
            file.save(file_path)
            
            # 返回相对路径，以便在URL中使用
            relative_path = os.path.relpath(file_path, current_app.root_path).replace('\\', '/')
            
            return {
                'filename': filename,
                'original_filename': file.filename,
                'file_path': file_path,
                'relative_path': relative_path,
                'file_size': file_size,
                'content_type': file.content_type or 'application/octet-stream',
                'category': cls.get_file_category(file.filename)
            }, None
        except Exception as e:
            return None, f"文件保存失败: {str(e)}"
    
    @classmethod
    def delete_file(cls, file_path):
        """删除文件"""
        try:
            if os.path.exists(file_path):
                os.remove(file_path)
                return True, "文件删除成功"
            else:
                return False, "文件不存在"
        except Exception as e:
            return False, f"文件删除失败: {str(e)}"
    
    @classmethod
    def get_file_info(cls, file_path):
        """获取文件信息"""
        if not os.path.exists(file_path):
            return None
        
        try:
            stat = os.stat(file_path)
            filename = os.path.basename(file_path)
            ext = filename.rsplit('.', 1)[1].lower() if '.' in filename else ''
            
            return {
                'filename': filename,
                'file_path': file_path,
                'file_size': stat.st_size,
                'created_time': datetime.fromtimestamp(stat.st_ctime),
                'modified_time': datetime.fromtimestamp(stat.st_mtime),
                'extension': ext,
                'category': cls.get_file_category(filename),
                'is_image': ext in cls.ALLOWED_EXTENSIONS.get('image', []),
                'is_document': ext in cls.ALLOWED_EXTENSIONS.get('document', [])
            }
        except Exception as e:
            return None